package org.lex.game.sudoku.view;

import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.border.Border;

import org.lex.game.sudoku.SudokuApplication;
import org.lex.game.sudoku.datatype.BoardStatus;
import org.lex.game.sudoku.datatype.HintType;
import org.lex.game.sudoku.model.Point;
import org.lex.game.sudoku.model.SudokuModel;
import org.lex.game.sudoku.view.cell.CellView;
import org.lex.game.sudoku.view.cell.LabelCellView;

public class SudokuBoard extends JPanel {

	private static final long serialVersionUID = -6487347218099217413L;
	// views widgets
	private CellView[][] cells; // Array of fields.
	private JPanel[][] boxPanes; // Panels holding the fields.

	private final SudokuBoardController controller;

	/**
	 * Constructs the panel, adds sub panels and adds fields to these sub
	 * panels.
	 */
	public SudokuBoard(SudokuApplication application) {
		this.controller = new SudokuBoardController(application, this);
		this.initialize();
	}

	public void setSudokuModel(SudokuModel model) {
		this.controller.setSudokuModel(model);
	}

	public SudokuModel getSudokuModel() {
		return this.controller.getSudokuModel();
	}

	public void rollback(List<Operation> opList) {
		this.controller.rollback(opList);
	}

	public long getStartTime() {
		return this.controller.getStartTime();
	}

	public void setStartTime(long startTime) {
		this.controller.setStartTime(startTime);
	}

	public BoardStatus getStatus() {
		return this.controller.getStatus();
	}

	public void setStatus(BoardStatus newStatus) {
		this.controller.setStatus(newStatus);
	}

	public HintType getHintType() {
		return this.controller.getHintType();
	}

	public void setHintType(HintType hintType) {
		this.controller.setHintType(hintType);
	}

	public void addBoardListener(SudokuBoardListener listener) {
		this.controller.addBoardListener(listener);
	}

	public void removeBoardListener(SudokuBoardListener listener) {
		this.controller.removeBoardListener(listener);
	}

	public Point getSelectedCell() {
		return this.controller.getSelectedCell();
	}

	public void setFont(Font font) {
		super.setFont(font);
		if (null != this.cells) {
			for (CellView[] row : this.cells) {
				for (CellView cell : row) {
					cell.setFont(font);
				}
			}
		}
	}

	private void initialize() {
		this.setLayout(new GridLayout(3, 3));

		this.boxPanes = new JPanel[3][3];
		for (int row = 0; row < 3; row++) {
			for (int column = 0; column < 3; column++) {
				JPanel box = new JPanel(new GridLayout(3, 3));
				box.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
				this.add(box);
				this.boxPanes[row][column] = box;
			}
		}

		this.cells = new CellView[9][9];
		Border cellBorder = BorderFactory.createLineBorder(Color.BLACK, 1);
		Font cellFont = new Font(Font.DIALOG, Font.BOLD, 30);
		for (int row = 0; row < 9; row++) {
			for (int col = 0; col < 9; col++) {
				LabelCellView cell = new LabelCellView(row, col);
				cell.addKeyListener(this.controller);
				// cell.addActionListener(this.controller);
				cell.addMouseListener(this.controller);
				cell.setBorder(cellBorder);
				cell.setFont(cellFont);

				cells[row][col] = cell;
				boxPanes[row / 3][col / 3].add(cell);
			}
		}
	}

	CellView getCellViews(int row, int column) {
		return this.cells[row][column];
	}
}